﻿// bugTest.cpp: 定义应用程序的入口点。
//
#define _CRT_SECURE_NO_WARNINGS  // 禁用安全警告

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
class BugTemplate {
public:
    virtual void FixTest() = 0;
};

//存在1个bug:每调用一个函数，系统就会在栈内存上为该函数分配一块空间（栈帧），由于StringToUpper和StringToLower返回的是一个在函数中创建的对象temp，属于局部变量，
//当对象出了作用域后就会死亡了，其在堆上申请的那空间也会被释放，由一个临时变量深拷贝局部变量的内容（堆上开辟另外一段空间存储），并传给test1和test2;当test1，test2创建完成后（表达式结束后消亡）
//临时变量也消亡了，系统回收临时变量开辟的那块存储数据的空间，但是临时变量开辟的那一块空间仍旧被test1,test2指向，因此就导致了一个问题：非法访问，它指向了一个已经释放了的临时对象的内存
class ClassBug :public BugTemplate
{
private:
    const std::string StringToUpper(const char* src)
    {
        std::string temp;
        temp = src;
        std::transform(temp.begin(), temp.end(), temp.begin(), ::toupper);
        return temp;
    }

    const std::string StringToLower(const char* src)
    {
        std::string temp;
        temp = src;
        std::transform(temp.begin(), temp.end(), temp.begin(), ::tolower);
        return temp;
    }

public:
    ClassBug() {}
    ~ClassBug() {}
    //需要修复乱码问题
    //tip:考察对类的作用域理解
    virtual void FixTest()
    {
        std::cout << "请修复bug，使程序正确输出转大写转小写" << std::endl;
        const char* test = "ABCddasdasdaddaweqWADfFcddasdasdaddaweqewabcddasdasdaddaweWQD";
        //修改为string：这里实际上是调用了构造函数(临时变量类型是const std::string与test1,test2不一样，所以是构造函数，不是拷贝构造)
        std::string test1 = StringToUpper(test).c_str();
        std::string test2 = StringToLower(test).c_str();
        std::cout << test << std::endl;
        std::cout << test1 << std::endl;
        std::cout << test2 << std::endl;

    }

};

struct buffertest {
   /* char strbuffer1[8];
    char strbuffer2[8];
    char strbuffer3[8];*/
    //第一个bug:由于需要对字符串存储字符串终止符'\0'，因此需要扩一位
    char strbuffer1[9];
    char strbuffer2[9];
    char strbuffer3[9];
};
//存在3个bug
class CopyBug :public BugTemplate
{
public:
    CopyBug() {}
    ~CopyBug() {}
    //需要修复乱码问题
    virtual void FixTest()
    {
        std::cout << "请让程序能够正常输出ABCDEFGHIJKLMNOP" << std::endl;
        buffertest* buffer = (buffertest*)malloc(sizeof(buffertest));
        //第二个bug:开辟空间并没有进行检查
        if (buffer == nullptr)
        {
            std::cerr << "内存分配失败" << std::endl;
            return;
        }

        strcpy(buffer->strbuffer2, "IJKLMNOP");
        strcpy(buffer->strbuffer1, "ABCDEFGH");

        std::cout << buffer->strbuffer1;
        std::cout << buffer->strbuffer2 << std::endl;
        //第三个bug:未能释放内存，造成内存泄漏,可以使用智能指针
        free(buffer);
        buffer = nullptr;
    }
};

//存在一个bug
class VectorBug :public BugTemplate
{
public:
    VectorBug() {}
    ~VectorBug() {}
    virtual void FixTest()
    {
        std::vector<int> vec = { 1,2,3,4,5,6,7,8,9 };
        std::cout << "正确使用迭代器删除程序前三个数值,使程序不崩溃" << std::endl;
        std::vector<int>::iterator it = vec.begin();
        for (int i = 0; i < 3; i++)
        {
            //An iterator pointing to the new location of the element that followed the last element erased by the function call. This is the container end if the operation erased the last element in the sequence.
            //说明了earse在删除后，会返回的是一个指向该元素的下一个元素，如果删除的是最后一个元素，那就指向end(),因此无需++；
            //程序崩溃的原因：C++标准是删除点以及其之后的所有迭代器以及其引用都会失效，而之前的迭代器和引用依旧正常，因此删除该点后，迭代器失效后++，就是非法访问了
            //vec.erase(it);
            //it++;
            it=vec.erase(it);
        }
        for (it = vec.begin(); it != vec.end(); it++)
        {
            std::cout << *it << " ";
        }

    }
};


//修复bug 使程序正常运作
int main()
{
    {
        ClassBug bug;
        bug.FixTest();
    }
    {
        CopyBug bug;
        bug.FixTest();
    }
    {
        VectorBug bug;
        bug.FixTest();
    }
    system("pause");
    return 0;
}
